//
//  engine.cpp
//  template4
//
//  Created by Xiaochen Lian on 5/15/12.
//  Copyright (c) 2012 University of California, Los Angeles. All rights reserved.
//

#include "engine.h"

CEngine::CEngine( /*GLfloat fovy, GLfloat aspect, GLfloat zNear, GLfloat zFar*/)
{
    //        this->fovy = fovy;
    //        this->aspect = aspect;
    //        this->zNear = zNear;
    //        this->zFar = zFar;
    body = NULL;
}

void CEngine::init()
{
    program = InitShader( "vshader.glsl", "fshader.glsl" );
    glUseProgram(program);
    
    uModelView  = glGetUniformLocation( program, "ModelView"  );
    uProjection = glGetUniformLocation( program, "Projection" );
    uCameraView = glGetUniformLocation( program, "CameraView" );
    
    glClearColor( 0.1, 0.1, 0.2, 1.0 ); // dark blue background
    
    uAmbient   = glGetUniformLocation( program, "AmbientProduct"  );
    uDiffuse   = glGetUniformLocation( program, "DiffuseProduct"  );
    uSpecular  = glGetUniformLocation( program, "SpecularProduct" );
    uLightPos  = glGetUniformLocation( program, "LightPosition"   );
    uShininess = glGetUniformLocation( program, "Shininess"       );
    uTex       = glGetUniformLocation( program, "Tex"             );
    uEnableTex = glGetUniformLocation( program, "EnableTex"       );
    
    glEnable(GL_DEPTH_TEST);
    
}

void CEngine::build_scene()
{
    eye = vec4(0.0, 50.0, 0.0, 0.0);
    ref = vec4(0.0);
    up = vec4(0.0, 0.0, -1.0, 0.0);
    mat4 view = LookAt(eye, ref, up);
    glUniformMatrix4fv( uCameraView, 1, GL_TRUE, view );
    
    glUniform4f(uLightPos,  15.0f, 15.0f, 30.0f, 1.0f);
    g_env_lighting.ambient = color4(0.2f,  0.2f,  0.2f, 1.0f);
    g_env_lighting.diffuse = color4(0.6f,  0.6f,  0.6f, 1.0f);
    g_env_lighting.specular = color4(0.2f,  0.2f,  0.2f, 1.0f);
    g_env_lighting.shininess = 100.0f;
    
    
    // Generate vertex arrays for geometric shapes
    vec3 body_scale(3.0, 3.0, 15.0);
    generateCube(program, &cubeData);
    generateSphere(program, &sphereData);
    generateEllipsoid(program, &ellipsData, body_scale);
    generateCone(program, &coneData);
    generateCylinder(program, &cylData);
    
    
    body = new CBody(body_scale, vec4(0.0f));
    body->build_model();
}

void CEngine::display()
{
    //    mat4 view = model_view;
    //    glUniformMatrix4fv( uView, 1, GL_TRUE, view );
    
    //    // Previously glScalef(Zoom, Zoom, Zoom);
    //    model_view *= Scale(Zoom);
    //
    //    // Draw Something
    //    set_colour(0.8f, 0.8f, 0.8f);
    //    drawSphere();
    //
    // Previously glTranslatef(3,0,0);
    //model_view *= Translate(3.0f, 0.0f, 0.0f);
    
    // Previously glScalef(3,3,3);
    //model_view *= Scale(3.0f, 3.0f, 3.0f);
    
    body->draw(model_view);
    
    //    drawCube();
    //
    //    // And extra shapes!
    //    model_view *= Scale(1.0f/3.0f, 1.0f/3.0f, 1.0f/3.0f);
    //    model_view *= Translate(3.0f, 0.0f, 0.0f);
    //    set_colour(1.0f, 1.0f, 0.0f);
    //    drawCone();
    //
    //    model_view *= Translate(-9.0f, 0.0f, 0.0f);
    //    set_colour(1.0f, 1.0f, 1.0f);
    //    drawCylinder();
    
    
    glutSwapBuffers();
    //    if(Recording == 1)
    //        FrSaver.DumpPPM(Width, Height) ;
}

//    void rotate_camera(const GLfloat dpitch, const GLfloat dyaw)
//    {
//        camera.pitch += dpitch;
//        camera.yaw += dyaw;
//    }
//    
//    void move_camera(int d)
//    {
//        GLfloat unit = 4.0;
//        switch (d) {
//            case 0:// w
//                camera.eye.z -= cos(camera.pitch*DegreesToRadians)*cos(-camera.yaw*DegreesToRadians) * unit;
//                camera.eye.x += cos(camera.pitch*DegreesToRadians)*sin(-camera.yaw*DegreesToRadians) * unit;
//                camera.eye.y += sin(camera.pitch*DegreesToRadians) * unit;
//                break;
//            case 1://a
//                camera.eye.x -= cos(camera.pitch*DegreesToRadians)*cos(camera.yaw*DegreesToRadians) * unit;
//                camera.eye.z += cos(camera.pitch*DegreesToRadians)*sin(camera.yaw*DegreesToRadians) * unit;
//                break;
//            case 2://d
//                camera.eye.x += cos(camera.pitch*DegreesToRadians)*cos(camera.yaw*DegreesToRadians) * unit;
//                camera.eye.z -= cos(camera.pitch*DegreesToRadians)*sin(camera.yaw*DegreesToRadians) * unit;
//                break;
//            case 3://s
//                camera.eye.z += cos(camera.pitch*DegreesToRadians)*cos(-camera.yaw*DegreesToRadians) * unit;
//                camera.eye.x -= cos(camera.pitch*DegreesToRadians)*sin(-camera.yaw*DegreesToRadians) * unit;
//                camera.eye.y -= sin(camera.pitch*DegreesToRadians) * unit;
//                break;
//            default:
//                break;
//        }
//    }
//
//    void set_aspect(GLfloat aspect)
//    {
//        this->aspect = aspect;
//    }
